class Category < ActiveRecord::Base
  
  validates_presence_of :name
  
  belongs_to :parent,
             :class_name => "Category",
             :foreign_key => "parent_id"
  
  has_many :children,
           :class_name => "Category",
           :foreign_key => "parent_id"
  
  validates_uniqueness_of :name
  
  #Any method that returns a category or list of categories
  # should first call load_categories, to ensure the categories
  # are in memory, or the parent/children overrides won't work
  class << self
    alias_method :old_find, :find
  end
  
  def self.find(*args)
    load_categories unless defined? @@list
    old_find(*args)
  end
  
  def self.list
    load_categories unless defined? @@list
    return @@list[1...@@list.length]    
  end
  
  def self.find_by_id(id_to_find)
    load_categories unless defined? @@list
    return @@list[id_to_find.to_i]
  end
  
  #parent/children methods override the ones provided by rails
  # to use the array instead of an SQL query
  def children
    @@children[id]
  end
  
  def children?
    @@children[id].empty?
  end
  
  def parent
    @@list[parent_id] unless parent_id.nil?   
  end
  
  def ancestry
    ancestry_array = Array.new
    c = self
    until c.parent.nil?
      ancestry_array << c.parent
      c = c.parent
    end
    return ancestry_array
  end
  
  def show_ancestry
    hierarchy = "<b>" + self.name + "</b>"
    ancestry.each {|an| hierarchy = an.name + " &gt; " + hierarchy}
    return hierarchy    
  end
  
  def self.root_categories
    @@children[0]
  end
  
  def make_select_option(level)
    level += 1
    select_option = "<option value=\"#{id}\">" + ("---" * (level-1)) + name + "</option>"
    children.each do |child|
      select_option << child.make_select_option(level)
    end
    return select_option
  end
  
  def self.create_select_options
    load_categories unless defined? @@list
    options = ""
    root_categories.each do |root|
      options << root.make_select_option(0)
    end
    return options
  end
  
  private 
  
  #loads all categories into memory, including parent>child relationships
  # to cut out any SQL queries and make processing more efficient
  def self.load_categories
    @@list = Array.new
    @@children = Array.new
    @@children[0] = Array.new #initialize master category
    all.each do |cat|
      @@list[cat.id] = cat
      @@children[cat.id] ||= Array.new
      @@children[(cat.parent_id || 0)] << @@list[cat.id] 
    end
  end
end